package com.loe.logger.util;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.loe.logger.R;

/**
 * 移动View
 */
public class SeekVerticalView extends View
{
    private Drawable drawable;

    private float imageWidth = 0.01f;
    private float imageHeight = 0.01f;

    private float x, y = 0f;
    private float imageY = 0f;

    private boolean isDown = false;

    /** 滑动比例 */
    private float rate = 0f;

    /** 滑动范围限制 */
    private float minRate = 0f;
    private float maxRate = 1f;
    private float minY = 0f;
    private float maxY = 0f;
    /** 滑动长度 */
    private float len = 0f;

    /** 触摸范围延伸 */
    private float touchPadding = px(15);

    public SeekVerticalView(Context context)
    {
        super(context);
        init(null, 0);
    }

    public SeekVerticalView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        init(attrs, 0);
    }

    public SeekVerticalView(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        init(attrs, defStyle);
    }

    private void init(AttributeSet attrs, int defStyle)
    {
        final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.SeekVerticalView, defStyle, 0);

        imageWidth = a.getDimension(R.styleable.SeekVerticalView_seek_imageWidth, imageWidth);
        imageHeight = a.getDimension(R.styleable.SeekVerticalView_seek_imageHeight, imageHeight);
        touchPadding = a.getDimension(R.styleable.SeekVerticalView_seek_touchPadding, touchPadding);
        rate = a.getFloat(R.styleable.SeekVerticalView_seek_rate, rate);
        minRate = a.getFloat(R.styleable.SeekVerticalView_seek_minRate, minRate);
        maxRate = a.getFloat(R.styleable.SeekVerticalView_seek_maxRate, maxRate);

        if (a.hasValue(R.styleable.SeekVerticalView_seek_image))
        {
            drawable = a.getDrawable(R.styleable.SeekVerticalView_seek_image);
            drawable.setCallback(this);

            if (imageWidth == 0.01f)
            {
                imageWidth = drawable.getIntrinsicWidth();
            }
            if (imageHeight == 0.01f)
            {
                imageHeight = drawable.getIntrinsicHeight();
            }
        }

        a.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);

        if (drawable != null)
        {
            drawable.setBounds((int) x, (int) y, (int) (x + imageWidth), (int) (y + imageHeight));
            drawable.draw(canvas);
        }
    }

    private int w, h;

    private int pTop, pBottom, pLeft, pRight;

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        // 宽度自适应
        w = MeasureSpec.getSize(widthMeasureSpec);
        h = MeasureSpec.getSize(heightMeasureSpec);
        pTop = getPaddingTop();
        pBottom = getPaddingBottom();
        pLeft = getPaddingLeft();
        pRight = getPaddingRight();
        if (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY)
        {
            w = (int) (pLeft + imageWidth + pRight);
        }
        if (MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY)
        {
            h = (int) (pTop + imageHeight + pBottom);
        }

        len = h - pTop - pBottom - imageHeight;
        minY = minRate * len + pTop;
        maxY = maxRate * len + pTop;
        y = rate * len + pTop;
        x = pLeft + (w - pLeft - pRight - imageWidth) / 2f;
        setMeasuredDimension(w, h);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        float ty = event.getY();
        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                if (y - touchPadding < ty && ty < y + imageHeight + touchPadding)
                {
                    isDown = true;
                    imageY = ty - y;
                    return true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (isDown)
                {
                    y = ty - imageY;
                    if (y < minY)
                    {
                        y = minY;
                    }
                    else if (y > maxY)
                    {
                        y = maxY;
                    }
                    rate = (y - pTop) / len;
                    invalidate();
                    if(onSeekRateListener != null) onSeekRateListener.onRate(rate);
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                isDown = false;
                break;
        }
        return false;
    }

    private int px(float dp)
    {
        return (int) (dp * Resources.getSystem().getDisplayMetrics().density + 0.5);
    }

    public void setRate(float rate)
    {
        this.rate = rate;
        y = rate * len + pTop;
        invalidate();
        if(onSeekRateListener != null) onSeekRateListener.onRate(rate);
    }

    public float getRate()
    {
        return rate;
    }

    public void setTouchPadding(float touchPadding)
    {
        this.touchPadding = touchPadding;
    }

    public void setMinRate(float minRate)
    {
        this.minRate = minRate;
        minY = minRate * len + pTop;
    }

    public void setMaxRate(float maxRate)
    {
        this.maxRate = maxRate;
        maxY = maxRate * len + pTop;
    }

    private OnSeekRateListener onSeekRateListener;

    public void setOnSeekRateListener(OnSeekRateListener onSeekRateListener)
    {
        this.onSeekRateListener = onSeekRateListener;
    }

    public interface OnSeekRateListener
    {
        void onRate(float rate);
    }
}